
#include <vector>
#include <algorithm>
#include "raylib.h"
#include <monster.h>
#include <mapbase.h>
#include <GameScene.h>
#include "search/bfszx.h"
#include <queue>
#include <thread>
using namespace std;

struct compare{
    bool operator()(std::pair<int,int> a, std::pair<int,int> b) {
        return a.first < b.first; 
    }
};

vector<float> Monster::getCollisionBox()
{
    vector<float> collisionBox;
    collisionBox.push_back(x+6);
    collisionBox.push_back(y);
    collisionBox.push_back(x+width+4);
    collisionBox.push_back(y+height);

    return collisionBox;
}

Rectangle Monster::getRectangle()
{
    Rectangle temp={x+6,y,width-2,height};
    return temp;
}

Texture Monster::initTexture(string imgPath){
    // 使用c_str()正确获取C风格字符串
    Image character = LoadImage(imgPath.c_str());
    ImageResize(&character, 120, 160);
    Texture chara_texture = LoadTextureFromImage(character);
    // SetTextureFilter(chara_texture,TEXTURE_FILTER_POINT);
    UnloadImage(character);
    return chara_texture;
}

void Monster::setInitialPosition(float x,float y)
{
    Vector2 temp={x,y};
    this->position=temp;
}

Vector2 Monster::getPosition()
{
    return {this->x,this->y};
}

//缩放大小的时候一定要等比例同步改这四个50的变量
void Monster::changeDirection(int direction)
{
    vector<Rectangle> frames;
    frames.reserve(3); // 预留空间提高效率
    
    // 根据方向计算Y坐标（不同方向对应不同行）
    int directions[4]={3,2,0,1};
    float yPos = directions[direction] * 40;
    
    for (int i = 0; i < 3; i++)
    {
        frames.push_back({
            (float)(i * 40),  // X坐标
            yPos,            // Y坐标（根据方向变化）
            40.0f,        // 宽度
            40.0f       // 高度
        });
    }
    actionFrames=frames;
}

void Monster::setGameScene(GameScene *gameScene){this->gameScene=gameScene;}

void Monster::updateFromGameScene(GameScene* scene)
{
    if(scene){this->nearbyBlocks = scene->getMonsterNearbyBlocks();}
}
/**
 * 只是根据当前方向尝试移动，并进行碰撞检测，不处理方向改变等逻辑问题
 */
void Monster::handleMovement()
{
    //获取周围的墙壁
    std::vector<Rectangle> nearWalls=nearbyBlocks[1];

    if (nearWalls.empty()) {
        std::cout<<"没有拿到墙壁数据"<<std::endl;
        return;
    }
    bool collisionFlag=false;
    // 保存原始位置
    float originalX = this->x;
    float originalY = this->y;

    switch (direction) {
        case 0: this->run_up(this->step); break;
        case 1: this->run_right(this->step); break;
        case 2: this->run_down(this->step); break;
        case 3: this->run_left(this->step); break;
    }

    Rectangle selfBox=this->getRectangle();
    for(int i=0;i<nearWalls.size();i++)
    {
        collisionFlag=getCollision(selfBox,nearWalls[i]);
        hitWalls=collisionFlag;
        if(collisionFlag)break;
    }
    // 如果碰撞，恢复位置
    if(collisionFlag) {
        this->x = originalX;
        this->y = originalY;
    }
}

void Monster::getToNearbyBlocksForChase()
{
    //获取周围的可移动草地块
    std::vector<Rectangle> nearFloor=nearbyBlocks[0];

    if (nearFloor.empty()) {
        std::cout<<"没有拿到地块数据"<<std::endl;
        return;
    }
    std::pair<float,Rectangle> result={400.0f,nearFloor[0]};
    Rectangle monsterCenter = {this->x + 24.0f, this->y + 24.0f, 48.0f, 48.0f};
    if (nearFloor.empty()) {
        std::cout<<"没有拿到草数据"<<std::endl;
        return;
    }
    for(int i=0;i<nearFloor.size();i++)
    {
        Rectangle block=nearFloor[i];
        Rectangle grassCenter = {block.x + 24.0f, block.y + 24.0f, 48.0f, 48.0f};
        float distance=sqrt(pow(monsterCenter.x - grassCenter.x, 2) + pow(monsterCenter.y - grassCenter.y, 2));
        if(distance<result.first)
        {
            result.first=distance;
            result.second=block;
        }
    }
    this->x=result.second.x;
    this->y=result.second.y;
}

bool isCloseEnough(Vector2 pos1, Vector2 pos2, float threshold) {
    float dx = pos1.x - pos2.x;
    float dy = pos1.y - pos2.y;
    return (dx * dx + dy * dy) < (threshold * threshold); 
}

//正交方向一定范围内出现目标
std::pair<bool, int> Monster::existHeroInCR()
{
    Vector2 heroPosition = gameScene->getHeroPosition();
    Rectangle heroBox = {heroPosition.x, heroPosition.y, 48, 48};
    
    // 检查水平方向
    for(int i = -3; i <= 3; i++) {
        if(i == 0) continue;
        
        float checkX = this->x + i * 48;
        float checkY = this->y;
        Rectangle checkBox = {checkX, checkY, 48, 48};
        
        if(CheckCollisionRecs(checkBox, heroBox)) {
            if(i > 0)
                return {true, 1}; // 右边
            else
                return {true, 3}; // 左边
        }
    }
    // 检查垂直方向
    for(int i = -3; i <= 3; i++) {
        if(i == 0) continue; 
        
        float checkX = this->x;
        float checkY = this->y + i * 48; 
        Rectangle checkBox = {checkX, checkY, 48, 48};
        
        if(CheckCollisionRecs(checkBox, heroBox)) {
            if(i > 0)
                return {true, 2}; // 下边
            else
                return {true, 0}; // 上边
        }
    }
    
    return {false, 0};
}

int Monster::getChaseNextDirection()
{
    if(chasePathIndex >= chasePath.size()) {
        return -1; // -1表示路径结束
    }
    
    Vector2 currentPos = {this->x + width/2, this->y + height/2};
    Vector2 nextPos = {(float)chasePath[chasePathIndex].x * 48 + 24, 
                       (float)chasePath[chasePathIndex].y * 48 + 24};
    
    if(isCloseEnough(currentPos, nextPos, 5.0f)) {
        return -1;
    }
    
    float dx = nextPos.x - currentPos.x;
    float dy = nextPos.y - currentPos.y;
    
    // 优先选择变化较大的轴
    if(abs(dx) > abs(dy)) {
        return (dx > 0) ? 1 : 3; // 右或左
    } else {
        return (dy > 0) ? 2 : 0; // 下或上
    }

}


void Monster::updateNextChasePoint()
{
    if(chasePathIndex >= chasePath.size())
        return;
    
    Vector2 nextPos = {(float)chasePath[chasePathIndex].x * 48 + 24, 
                       (float)chasePath[chasePathIndex].y * 48 + 24}; 
    
    if(isCloseEnough({this->x + 24.0f, this->y + 24.0f}, nextPos, 18.0f))
    {
        getToNearbyBlocksForChase();
        chasePathIndex++;
        
        if(chasePathIndex >= chasePath.size()) {
            reachedPathEnd = true;
        }
    }
}
//根据路径搜索的路线来变向
void Monster::changeDirectionInChase()
{
    // if(reachedPathEnd) {
    //     auto heroDetection = existHeroInCR();
    //     if(heroDetection.first) {
    //         // 重新计算路径
    //         std::vector<std::vector<Coord<int>>> paths = bfszx(
    //             map->getMap(),
    //             { static_cast<int>(hero->x / 48), static_cast<int>(hero->y / 48) },
    //             { static_cast<int>(this->x / 48), static_cast<int>(this->y / 48) },
    //             false
    //         );
            
    //         if(!paths.empty() && !paths[0].empty()) {
    //             chasePath = paths[0];
    //             chasePathIndex = 0;
    //             reachedPathEnd = false;
    //         } else {
    //             // 如果找不到路径，使用简单追逐
    //             useSimpleChaseAtEnd();
    //             return;
    //         }
    //     } else {
    //         chasing = false;
    //         return;
    //     }
    // }
    
    updateNextChasePoint();
    int nextDirection = getChaseNextDirection();
    
    if(nextDirection != -1) {
        this->direction = nextDirection;
        changeDirection(direction);
    } else {
        if(chasePathIndex < chasePath.size()) {
            chasePathIndex++;
        }
    }
}
//简单追逐
void Monster::useSimpleChaseAtEnd()
{
    Vector2 heroPosition = gameScene->getHeroPosition();
    Vector2 monsterPosition = {this->x, this->y};
    
    float dx = heroPosition.x - monsterPosition.x;
    float dy = heroPosition.y - monsterPosition.y;
    
    // 简单朝向英雄方向
    if(abs(dx) > abs(dy)) {
        this->direction = (dx > 0) ? 1 : 3;
    } else {
        this->direction = (dy > 0) ? 2 : 0;
    }
    
    changeDirection(direction);
    
    // 如果持续撞墙，尝试随机方向
    static int stuckCount = 0;
    if(hitWalls) {
        stuckCount++;
        if(stuckCount > 10) { // 连续10帧撞墙
            this->direction = getRand(0, 3);
            changeDirection(direction);
            stuckCount = 0;
        }
    } else {
        stuckCount = 0;
    }
}

void Monster::updateShowInformations(){ }

int Monster::getRightDirection()
{
    Rectangle selfRec=this->getRectangle();
    std::vector<Rectangle> nearWalls=nearbyBlocks[1];
    priority_queue<std::pair<int,int>,vector<std::pair<int,int>>,compare> priorityDirections;
    for(int i=0;i<4;i++)
    {
        Rectangle testRec=selfRec;
        bool inWall=false;
        int forwardCount=0;
        switch(i)
        {
            case 0:
                do{
                    testRec.y-=48;
                    if(forwardCount>=3)
                    {
                        priorityDirections.push(std::make_pair(3,0));
                        inWall=true;
                        break;
                    }else
                    {
                        forwardCount++;
                    }
                    for(Rectangle wall:nearWalls)
                    {
                        if(getCollision(testRec,wall))
                        {
                            priorityDirections.push(std::make_pair(forwardCount,0));
                            inWall=true;
                            break;
                        }
                    }
                }while(!inWall);
                break;
            case 1:
                do{
                    testRec.x+=48;
                    if(forwardCount>=3)
                    {
                        priorityDirections.push(std::make_pair(3,0));
                        inWall=true;
                        break;
                    }else
                    {
                        forwardCount++;
                    }
                    for(Rectangle wall:nearWalls)
                    {
                        if(getCollision(testRec,wall))
                        {
                            priorityDirections.push(std::make_pair(forwardCount,1));
                            inWall=true;
                            break;
                        }
                    }
                }while(!inWall);
                break;
            case 2:
                do{
                    testRec.y+=48;
                    if(forwardCount>=3)
                    {
                        priorityDirections.push(std::make_pair(3,0));
                        inWall=true;
                        break;
                    }else
                    {
                        forwardCount++;
                    }
                    for(Rectangle wall:nearWalls)
                    {
                        if(getCollision(testRec,wall))
                        {
                            priorityDirections.push(std::make_pair(forwardCount,2));
                            inWall=true;
                            break;
                        }
                    }
                }while(!inWall);
                break;
            case 3:
                do{
                    testRec.x-=48;
                    if(forwardCount>=3)
                    {
                        priorityDirections.push(std::make_pair(3,0));
                        inWall=true;
                        break;
                    }else
                    {
                        forwardCount++;
                    }
                    for(Rectangle wall:nearWalls)
                    {
                        if(getCollision(testRec,wall))
                        {
                            priorityDirections.push(std::make_pair(forwardCount,3));
                            inWall=true;
                            break;
                        }
                    }
                }while(!inWall);
                break;
        }
    }
    if(priorityDirections.empty()) return getRand(0, 3);
    return priorityDirections.top().second;
}

void Monster::handleChangeDirection()
{
    if(!this) return;
    
    auto end = clock();
    updateLevelTime(double(end - start) / CLOCKS_PER_SEC);
    
    // 进入下一个追逐时间前不会再判断追逐
    if(double(end - start) / CLOCKS_PER_SEC > chase_time) {
        chasing = false;
        step = originStep;
        chasePath.clear();
        reachedPathEnd = false; // 重置到达终点标志
        
        auto heroDetection = existHeroInCR();
        
        if(heroDetection.first) { // 如果检测到英雄
            getToNearbyBlocksForChase();
            chasing = true;
            chase_direction = heroDetection.second;
            
            // 重置定时器，开始追逐
            start = end;
            step *= 1.5f; // 追逐时加速
            
            // 计算路径
            std::vector<std::vector<Coord<int>>> paths = bfszx(
                map->getMap(),
                { static_cast<int>(hero->x / 48), static_cast<int>(hero->y / 48) },
                { static_cast<int>(this->x / 48), static_cast<int>(this->y / 48) },
                false
            );
            
            if(!paths.empty() && !paths[0].empty()) {
                chasePath = paths[0];
                chasePathIndex = 0;
                reachedPathEnd = false;
            } else {
                chasing = false; // 无法找到路径，取消追逐
            }
        }
    }
    
    if(chasing && (double(end - start) / CLOCKS_PER_SEC) < chase_time) {
        changeDirectionInChase();
        return;
    }

    if(!chasing) {
        updateLevelTime(double(end - start) / CLOCKS_PER_SEC);
        // 正常的定时随机变向
        if((double(end - start) / CLOCKS_PER_SEC) > 1.02f) {
            this->direction = getRightDirection();
            changeDirection(direction);
            start = end;
        }
    }
}
